#include "MetadataSvrClient.h"
#include "MetadataSvrCommon.h"
#include "ProtoHelper.h"
#include "MetadataSvrClientProtoHelper.h"


LoggerPtr MetadataSvrClient::_logger = Logger::getLogger("MetadataSvrClient");

int MetadataSvrClient::init(const char * svr_ip, const unsigned svr_port, const int conn_pool_size, const int conn_timeout, \
                                const int send_timeout, const int recv_timeout, const int max_response_size) {
	if (NULL == svr_ip || conn_pool_size < 1) {
		LOG4CXX_ERROR(_logger, "init error, invalid args");
		return -1;
	}
	_svr_ip = svr_ip;
	_svr_port = svr_port;
	_conn_pool_size = conn_pool_size;
	_conn_timeout = conn_timeout;
	_send_timeout = send_timeout;
	_recv_timeout = recv_timeout;
	_max_response_size = max_response_size;
	int ret = _pool.init(svr_ip, svr_port, conn_timeout, conn_pool_size);
        if (ret < 0) {
                LOG4CXX_ERROR(_logger, "conn pool init error, ret:" << ret << ", svr_ip:" << svr_ip << ", svr_port:" << \
                                svr_port << ", conn_timeout:" << conn_timeout << ", conn_pool_size:" << conn_pool_size);
                return -2;
        }
        LOG4CXX_INFO(_logger, "MetadataSvrClient init ok, svr_ip:" << svr_ip << ", svr_port:" << svr_port << ", conn_timeout:" << \
                        conn_timeout << ", conn_pool_size:" << ", send_timeout:" << send_timeout << ", recv_timeout:" << \
                        recv_timeout);
        return 1;
}

int MetadataSvrClient::create_md_file(int32_t dir_id, int64_t file_id) {
	if (dir_id < 0 || file_id < 0) {
		LOG4CXX_ERROR(_logger, __FUNCTION__ <<", invalid args");
		return MDS_ERR_CLIENT_DETECTED_INVALID_ARGS;
	}
	SocketConnPtr cp;
        int ret = _pool.get(cp);
        if (ret < 0) {
                LOG4CXX_ERROR(_logger, __FUNCTION__ << ", could not get connection from pool, dir_id:" << dir_id << \
				", file_id:" << file_id);
                return MDS_ERR_CLIENT_TO_SVR_NETWORK_ERR;
        }
        string request = mds_build_request_create_md_file(dir_id, file_id);
        string response;
        ret = send_and_recv_cmd(cp, _send_timeout, _recv_timeout, request.c_str(), request.size(), _max_response_size, response);
        if (ret < 0) {
                LOG4CXX_ERROR(_logger, __FUNCTION__ << ", send and recv cmd error, ret:" << ret << ", dir_id:" << dir_id << \
				", file_id:" << file_id);
                return MDS_ERR_CLIENT_TO_SVR_NETWORK_ERR;
        }
	int result;
	ret = mds_parse_response_create_md_file(response.c_str(), result); 
	if (ret < 0) return MDS_ERR_INVALID_RESPONSE;
	return result;
}

int MetadataSvrClient::delete_md_file(int32_t dir_id, int64_t file_id) {
	if (dir_id < 0 || file_id < 0) {
		LOG4CXX_ERROR(_logger, __FUNCTION__ <<", invalid args");
		return MDS_ERR_CLIENT_DETECTED_INVALID_ARGS;
	}
	SocketConnPtr cp;
        int ret = _pool.get(cp);
        if (ret < 0) {
                LOG4CXX_ERROR(_logger, __FUNCTION__ << ", could not get connection from pool, dir_id:" << dir_id << \
				", file_id:" << file_id);
                return MDS_ERR_CLIENT_TO_SVR_NETWORK_ERR;
        }
        string request = mds_build_request_delete_md_file(dir_id, file_id);
        string response;
        ret = send_and_recv_cmd(cp, _send_timeout, _recv_timeout, request.c_str(), request.size(), _max_response_size, response);
        if (ret < 0) {
                LOG4CXX_ERROR(_logger, __FUNCTION__ << ", send and recv cmd error, ret:" << ret << ", dir_id:" << dir_id << \
				", file_id:" << file_id);
                return MDS_ERR_CLIENT_TO_SVR_NETWORK_ERR;
        }
	int result;
	ret = mds_parse_response_delete_md_file(response.c_str(), result); 
	if (ret < 0) return MDS_ERR_INVALID_RESPONSE;
	return result;
}

int MetadataSvrClient::get_md_file_info(int32_t dir_id, int64_t file_id, MD_FILE_INFO & info) {
	if (dir_id < 0 || file_id < 0) {
		LOG4CXX_ERROR(_logger, __FUNCTION__ <<", invalid args");
		return MDS_ERR_CLIENT_DETECTED_INVALID_ARGS;
	}
	SocketConnPtr cp;
        int ret = _pool.get(cp);
        if (ret < 0) {
                LOG4CXX_ERROR(_logger, __FUNCTION__ << ", could not get connection from pool, dir_id:" << dir_id << \
				", file_id:" << file_id);
                return MDS_ERR_CLIENT_TO_SVR_NETWORK_ERR;
        }
        string request = mds_build_request_get_md_file_info(dir_id, file_id);
        string response;
        ret = send_and_recv_cmd(cp, _send_timeout, _recv_timeout, request.c_str(), request.size(), _max_response_size, response);
        if (ret < 0) {
                LOG4CXX_ERROR(_logger, __FUNCTION__ << ", send and recv cmd error, ret:" << ret << ", dir_id:" << dir_id << \
				", file_id:" << file_id);
                return MDS_ERR_CLIENT_TO_SVR_NETWORK_ERR;
        }
	int result;
	ret = mds_parse_response_get_md_file_info(response.c_str(), result, info); 
	if (ret < 0) return MDS_ERR_INVALID_RESPONSE;
	return result;
}

int MetadataSvrClient::data_svr_notify_data_file_info(int32_t dir_id, int64_t file_id, int data_svr_id, int64_t file_size, \
                                                vector<uint32_t> crcs, int delete_flag, int notify_reason) {
	if (dir_id < 0 || file_id < 0) {
		LOG4CXX_ERROR(_logger, __FUNCTION__ <<", invalid args");
		return MDS_ERR_CLIENT_DETECTED_INVALID_ARGS;
	}
	SocketConnPtr cp;
        int ret = _pool.get(cp);
        if (ret < 0) {
                LOG4CXX_ERROR(_logger, __FUNCTION__ << ", could not get connection from pool, dir_id:" << dir_id << \
				", file_id:" << file_id);
                return MDS_ERR_CLIENT_TO_SVR_NETWORK_ERR;
        }
        string request = mds_build_request_data_svr_notify_data_file_info(dir_id, file_id, data_svr_id, file_size, crcs, \
				delete_flag, notify_reason);
        string response;
        ret = send_and_recv_cmd(cp, _send_timeout, _recv_timeout, request.c_str(), request.size(), _max_response_size, response);
        if (ret < 0) {
                LOG4CXX_ERROR(_logger, __FUNCTION__ << ", send and recv cmd error, ret:" << ret << ", dir_id:" << dir_id << \
				", file_id:" << file_id);
                return MDS_ERR_CLIENT_TO_SVR_NETWORK_ERR;
        }
	int result;
	ret = mds_parse_response_data_svr_notify_data_file_info(response.c_str(), result); 
	if (ret < 0) return MDS_ERR_INVALID_RESPONSE;
	return result;
}

int MetadataSvrClient::client_notify_client_data_info(int32_t dir_id, int64_t file_id, vector<uint32_t> crcs) {
	if (dir_id < 0 || file_id < 0) {
		LOG4CXX_ERROR(_logger, __FUNCTION__ <<", invalid args");
		return MDS_ERR_CLIENT_DETECTED_INVALID_ARGS;
	}
	SocketConnPtr cp;
        int ret = _pool.get(cp);
        if (ret < 0) {
                LOG4CXX_ERROR(_logger, __FUNCTION__ << ", could not get connection from pool, dir_id:" << dir_id << \
				", file_id:" << file_id);
                return MDS_ERR_CLIENT_TO_SVR_NETWORK_ERR;
        }
        string request = mds_build_request_client_notify_client_data_info(dir_id, file_id, crcs);
        string response;
        ret = send_and_recv_cmd(cp, _send_timeout, _recv_timeout, request.c_str(), request.size(), _max_response_size, response);
        if (ret < 0) {
                LOG4CXX_ERROR(_logger, __FUNCTION__ << ", send and recv cmd error, ret:" << ret << ", dir_id:" << dir_id << \
				", file_id:" << file_id);
                return MDS_ERR_CLIENT_TO_SVR_NETWORK_ERR;
        }
	int result;
	ret = mds_parse_response_client_notify_client_data_info(response.c_str(), result); 
	if (ret < 0) return MDS_ERR_INVALID_RESPONSE;
	return result;
}

int MetadataSvrClient::alloc_ds_4_new_file(int32_t & ds_id, int32_t & dir_id, int64_t & file_id) {
	SocketConnPtr cp;
        int ret = _pool.get(cp);
        if (ret < 0) {
                LOG4CXX_ERROR(_logger, __FUNCTION__ << ", could not get connection from pool");
                return MDS_ERR_CLIENT_TO_SVR_NETWORK_ERR;
        }
        string request = mds_build_request_alloc_ds_4_new_file();
        string response;
        ret = send_and_recv_cmd(cp, _send_timeout, _recv_timeout, request.c_str(), request.size(), _max_response_size, response);
        if (ret < 0) {
                LOG4CXX_ERROR(_logger, __FUNCTION__ << ", send and recv cmd error, ret:" << ret);
                return MDS_ERR_CLIENT_TO_SVR_NETWORK_ERR;
        }
	int result;
	ret = mds_parse_response_alloc_ds_4_new_file(response.c_str(), result, ds_id, dir_id, file_id); 
	if (ret < 0) return MDS_ERR_INVALID_RESPONSE;
	return result;

}
